using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace gears
{

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        List<GearWheel> gear_wheel = new List<GearWheel>();
        bool selected = false;
        GearWheel selected_gear;
        LevelManager level_manager;

        Texture2D menu_background;

        //For moving the Gears~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        Vector2 poss = new Vector2();

        //Game States~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        public enum State
        {
            Menu,
            Game,
            Options,
            Exit,
        };

        public static State gameState;

        Menu myMenu;
        Options myOptions;

        //~~~~~~~~~~~For transition~~~~~~~~~~~~~~
        public static float alpha;
        public static float globalAlpha;
        public static Texture2D backgroundTexture;
        private Texture2D logo;
        public static bool transition;
        public static bool backButtonPressed;


        public static int screenWidth;
        public static int screenHeight;

       

        //~~~~~~~~~~~For Sound~~~~~~~~~~~~~~~~~~~~~
        Song gameMusic;

        //~~~~~~~~~Sound Effects~~~~~~~~~~~~~~~~~~~
        public static SoundEffects mySoundEffects;
        SoundEffect menuGearEffect;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            TargetElapsedTime = TimeSpan.FromTicks(200000);

            InactiveSleepTime = TimeSpan.FromSeconds(1);
        }

        protected override void Initialize()
        {
            //Set the gameState to Menu~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            gameState = new State();
            gameState = State.Menu;
            
            //Set the screen widht & height~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            graphics.PreferredBackBufferHeight = 480;
            graphics.PreferredBackBufferWidth = 800;
            graphics.ApplyChanges();



            screenHeight = GraphicsDevice.DisplayMode.Height;
            screenWidth = GraphicsDevice.DisplayMode.Width;
            
            //Initialize the Menu class and give it the screen width and height~~~~
            myMenu = new Menu();
            myOptions = new Options();
            transition = false;
            backButtonPressed = false;

            //SoundEffects~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            mySoundEffects = new SoundEffects();

            Game1.alpha = 0f;

            Game1.globalAlpha = Game1.alpha;
           

            ContentLoader.Content = Content;

            base.Initialize();
        }


        protected override void LoadContent()
        {

            spriteBatch = new SpriteBatch(GraphicsDevice);

            gear_wheel.Add(new GearWheel(new Vector2(180, 345), 30, 0.01f, ContentLoader.LoadTexture("wireWheel"), ContentLoader.LoadTexture("wireTooth"), ContentLoader.LoadTexture("smallNumbers/num1")));
            gear_wheel[gear_wheel.Count - 1].IsFixed = true;
            gear_wheel[gear_wheel.Count - 1].Drived = true;
            gear_wheel.Add(new GearWheel(new Vector2(240, 170), 15, -0.02f, ContentLoader.LoadTexture("wireWheel"), ContentLoader.LoadTexture("wireTooth"), ContentLoader.LoadTexture("smallNumbers/num1")));
            gear_wheel[gear_wheel.Count - 1].IsFixed = true;
            gear_wheel[gear_wheel.Count - 1].Drived = true;
            gear_wheel.Add(new GearWheel(new Vector2(135, 168), 10, 0.03f, ContentLoader.LoadTexture("wireWheel"), ContentLoader.LoadTexture("wireTooth"), ContentLoader.LoadTexture("smallNumbers/num1")));
            gear_wheel[gear_wheel.Count - 1].IsFixed = true;
            gear_wheel[gear_wheel.Count - 1].Drived = true;
            gear_wheel.Add(new GearWheel(new Vector2(332, 434), 13, -0.02307f, ContentLoader.LoadTexture("wireWheel"), ContentLoader.LoadTexture("wireTooth"), ContentLoader.LoadTexture("smallNumbers/num1")));
            gear_wheel[gear_wheel.Count - 1].IsFixed = true;
            gear_wheel[gear_wheel.Count - 1].Drived = true;
            gear_wheel.Add(new GearWheel(new Vector2(450, 422), 15, 0.01999f, ContentLoader.LoadTexture("wireWheel"), ContentLoader.LoadTexture("wireTooth"), ContentLoader.LoadTexture("smallNumbers/num1")));
            gear_wheel[gear_wheel.Count - 1].IsFixed = true;
            gear_wheel[gear_wheel.Count - 1].Drived = true;
            gear_wheel.Add(new GearWheel(new Vector2(610, 410), 25, -0.01199f, ContentLoader.LoadTexture("wireWheel"), ContentLoader.LoadTexture("wireTooth"), ContentLoader.LoadTexture("smallNumbers/num1")));
            gear_wheel[gear_wheel.Count - 1].IsFixed = true;
            gear_wheel[gear_wheel.Count - 1].Drived = true;
            gear_wheel.Add(new GearWheel(new Vector2(605, 225), 20, 0.0149875f, ContentLoader.LoadTexture("wireWheel"), ContentLoader.LoadTexture("wireTooth"), ContentLoader.LoadTexture("smallNumbers/num1")));
            gear_wheel[gear_wheel.Count - 1].IsFixed = true;
            gear_wheel[gear_wheel.Count - 1].Drived = true;
            gear_wheel.Add(new GearWheel(new Vector2(675, 120), 10, -0.029975f, ContentLoader.LoadTexture("wireWheel"), ContentLoader.LoadTexture("wireTooth"), ContentLoader.LoadTexture("smallNumbers/num1")));
            gear_wheel[gear_wheel.Count - 1].IsFixed = true;
            gear_wheel[gear_wheel.Count - 1].Drived = true;

           
            // gear_wheel.Add(new GearWheel(new Vector2(530, 300), 170f, 0.02f, Content.Load<Texture2D>("gear_wheel3"), Content.Load<Texture2D>("tooth1")));
            // gear_wheel.Add(new GearWheel(new Vector2(150, 250), 50f, 0.03f, Content.Load<Texture2D>("gear_wheel1"), Content.Load<Texture2D>("tooth1")));
            // gear_wheel2 = new GearWheel(new Vector2(100, 250), 50f, 0.0f, Content.Load<Texture2D>("gear_wheel1"), Content.Load<Texture2D>("tooth1"));

            level_manager = new LevelManager(spriteBatch);
            //levelSheme = Content.Load<Texture2D>("level1Base");
            //~~For Transition Effect~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
            backgroundTexture = Content.Load<Texture2D>("bg");

            //Load the Menu Textures~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            myMenu.StartTexture = Content.Load<Texture2D>("startTexture");
            myMenu.OptionsTexture = Content.Load<Texture2D>("optionsTexture");
            myMenu.ExitTexture = Content.Load<Texture2D>("exitTexture");

            //Load the Options Textures~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            myOptions.ExitTexture = Content.Load<Texture2D>("exitTexture");

            //~~Load the Sounds and Sound Effects~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            gameMusic = Content.Load<Song>("Sound/gameMusic");

            mySoundEffects.Add("gear", Content.Load<SoundEffect>("SoundEffects/gearSound"));
            mySoundEffects.Add("death", Content.Load<SoundEffect>("SoundEffects/death"));
            mySoundEffects.Add("jump", Content.Load<SoundEffect>("SoundEffects/jump"));
            mySoundEffects.Add("door_open", Content.Load<SoundEffect>("SoundEffects/door_open"));

            

            //Load the Textures~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
            myOptions.SoundOn = Content.Load<Texture2D>("Sound/soundOn");
            myOptions.SoundOff = Content.Load<Texture2D>("Sound/soundOff");
            myOptions.SoundMin = Content.Load<Texture2D>("Sound/sound--");
            myOptions.SoundPlus = Content.Load<Texture2D>("Sound/sound++");

            myOptions.Brightness = Content.Load<Texture2D>("Sound/brightness");
            myOptions.BrightnessMin = Content.Load<Texture2D>("Sound/brightness--");
            myOptions.BrightnessPlus = Content.Load<Texture2D>("Sound/brightness++");

            myOptions.MyFont = Content.Load<SpriteFont>("Sound/myFont");

            

            //~~Start the background music right away~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            PlayMusic(gameMusic);

            menu_background = ContentLoader.LoadTexture("menu_background");

            logo = ContentLoader.LoadTexture("logo");
           
        }
        protected override void UnloadContent()
        {

        }

        protected override void Update(GameTime gameTime)
        {
            //Update the selected gameState~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            switch (gameState)
            {
                case State.Menu:
                    myMenu.Update(gameTime);
                    if (level_manager.GameEnded == true)
                    {
                        level_manager = new LevelManager(spriteBatch);
                    }
                    foreach (GearWheel gw in gear_wheel)
                    {
                        gw.Rotate();
                    }
                    break;
                case State.Game:
                    GameUpdate(gameTime);
                    break;
                case State.Options:
                    myOptions.Update(gameTime);
                    foreach (GearWheel gw in gear_wheel)
                    {
                        gw.Rotate();
                    }
                    break;
                case State.Exit:
                    this.Exit(); //Exit The Game
                    break;
            }
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

           
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();

            switch (gameState)
            {
                case State.Menu:
                    spriteBatch.Draw(menu_background, new Vector2(-10, -25), Color.White);
                    foreach (GearWheel gw in gear_wheel)
                    {
                        gw.Draw(spriteBatch);
                    }
                    spriteBatch.Draw(logo, new Vector2(250,0), Color.White);
                    myMenu.Draw(spriteBatch);
                    break;
                case State.Game:
                    GameDraw(spriteBatch);
                    break;
                case State.Options:
                    spriteBatch.Draw(menu_background, new Vector2(-10, -25), Color.White);
                    foreach (GearWheel gw in gear_wheel)
                    {
                        gw.Draw(spriteBatch);
                    }
                    myOptions.Draw(spriteBatch);
                    break;
                case State.Exit:
                    //~~Draw the Background last for the transition Effect~~~~~~~~~~~~~~~
                    spriteBatch.Draw(backgroundTexture, new Rectangle(0, 0, Game1.screenHeight, Game1.screenWidth), Color.White * alpha);
                    break;
            }
            //spriteBatch.Draw(levelSheme, new Rectangle(0, 0, Game1.screenHeight, Game1.screenWidth), Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }
       
        //Update the Game~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        private void GameUpdate(GameTime gameTime)
        {
            //Collision Detection for Gears~~~~~~~~~~~~~~~~~~~~
            foreach (GearWheel gw in gear_wheel)
            {
                gw.Rotate();

            }
            for (int i = 0; i < gear_wheel.Count - 1; i++)
            {
                gear_wheel[i].CheckCollisions(gear_wheel[i + 1]);
            }

            level_manager.Update(gameTime);

            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


            //Check if Back button is pressed
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                backButtonPressed = true;
            }
            if (backButtonPressed)
            {

                //Game1.mySoundEffects.Play("menuSound");
                //Transition Effect~~~~~~~~~~~~~~~~~~~~~~~~~~~
                    Game1.alpha += 0.05f;

                    if (Game1.alpha > 1f)
                    {
                        Game1.alpha = 1f;
                        Game1.transition = true;
                        backButtonPressed = false;
                        Game1.gameState = State.Menu;
                    }
                //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            }

            
        }

        //Draw the Game~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        private void GameDraw(SpriteBatch spriteBatch)
        {
            //Transition Effect~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            if (transition)
            {
                alpha -= 0.05f;

                if (alpha <= Game1.globalAlpha)
                {
                    alpha = Game1.globalAlpha;
                    transition = false;
                }
            }
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            foreach (GearWheel gw in gear_wheel)
            {
                gw.Draw(spriteBatch);
            }

            level_manager.LevelManagerDraw(spriteBatch);

            //~~Draw the Background last for the transition Effect~~~~~~~~~~~~~~~
            spriteBatch.Draw(backgroundTexture, new Rectangle(0, 0, Game1.screenHeight, Game1.screenWidth), Color.White * alpha);
       
        }

        //Other methods~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        public void PlayMusic(Song song)
        {
            // Due to the way the MediaPlayer plays music,
            // we have to catch the exception. Music will play when the game is not tethered
            try
            {
                // Play the music
                MediaPlayer.Play(song);

                // Loop the currently playing song
                MediaPlayer.IsRepeating = true;
            }
            catch { }
        }

    }
}
